package cn.autumnorange.authorization.security.security;

import cn.autumnorange.authorization.security.properties.OAuth2ClientProperties;
import cn.autumnorange.authorization.security.properties.OAuth2Properties;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.ClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import java.util.ArrayList;
import java.util.List;

/**
 * Created on 2018/1/15 0015.
 *
 * @author zlf
 * @email i@merryyou.cn @update wsf
 * @since 1.0
 */
@Configuration
@EnableAuthorizationServer
public class MerryyouAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

  @Autowired private OAuth2Properties oAuth2Properties;

  @Autowired private AuthenticationManager authenticationManager;

  @Autowired private UserDetailsService userDetailsServiceImpl;
  /**
   * 详见TokenStoreConfig类
   */
  @Autowired
  private TokenStore tokenStore;
  /**
   * Jwt访问令牌转换器
   */
  @Autowired(required = false)
  private JwtAccessTokenConverter jwtAccessTokenConverter;
  /**
   * 扩展jwttoken存储信息
   */
  @Autowired(required = false)
  private TokenEnhancer jwtTokenEnhancer;

  @Autowired private PasswordEncoder passwordEncoder;

  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints
            .tokenStore(tokenStore)
        .authenticationManager(authenticationManager)
        .userDetailsService(userDetailsServiceImpl);
    // 扩展token返回结果
    if (jwtAccessTokenConverter != null && jwtTokenEnhancer != null) {
      TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
      List<TokenEnhancer> enhancerList = new ArrayList();
      enhancerList.add(jwtTokenEnhancer);
      enhancerList.add(jwtAccessTokenConverter);
      tokenEnhancerChain.setTokenEnhancers(enhancerList);
      // jwt
      endpoints.tokenEnhancer(tokenEnhancerChain).accessTokenConverter(jwtAccessTokenConverter);
    }
  }

  /**
   * 配置客户端Client的一些信息
   *
   * @param clients
   * @throws Exception
   */
  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    InMemoryClientDetailsServiceBuilder build = clients.inMemory();
    if (ArrayUtils.isNotEmpty(oAuth2Properties.getClients())) {
      for (OAuth2ClientProperties config : oAuth2Properties.getClients()) {
        ClientDetailsServiceBuilder.ClientBuilder clientBuilder =
            build.withClient(config.getClientId());
        clientBuilder
            .secret(passwordEncoder.encode(config.getClientSecret()))
            .accessTokenValiditySeconds(config.getAccessTokenValiditySeconds())
            .refreshTokenValiditySeconds(config.getRefreshTokenValiditySeconds())
            .authorizedGrantTypes(config.getAuthorizedGrantTypes()) // OAuth2支持的验证模式
            .redirectUris(config.getRedirectUris())
            .scopes(config.getScopes())
            .autoApprove(true);
      }
    }
  }

  //    @Override
  //    public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
  //        //允许表单认证
  //        oauthServer.allowFormAuthenticationForClients();
  //        oauthServer.passwordEncoder(passwordEncoder);
  //    }

  /**
   * springSecurity 授权表达式，
   *
   * @param security
   * @throws Exception
   */
  @Override
  public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    security.tokenKeyAccess("permitAll()");
    security.checkTokenAccess("isAuthenticated()");
  }
}
